import assert from "assert";
import path from "path";
import { pathToFileURL } from "url";
import { SystemJS } from "../dist/s.js";
import fetch, { Response } from "node-fetch";

import { promises as fs } from "fs";

/**
 * ! You can just use applyImportMap and setBaseUrl in System!
 */

describe("NodeJS version of SystemJS", () => {
    beforeEach(() => {
        global.System = new SystemJS();
        System.setBaseUrl(pathToFileURL(process.cwd() + "/").href);
        System.fetch = async function (url, options) {
            if (url.startsWith("file://")) {
                return fs
                    .readFile(url.replace("file://", ""), "utf-8")
                    .then((res) => {
                        return new Response(res, {
                            headers: {
                                "content-type": "text/javascript",
                            },
                        });
                    });
            } else {
                return fetch.call(this, url, options);
            }
        };
    });

    describe("resolve", () => {
        it("provides a default base url if one is not specified", () => {
            assert.equal(
                System.resolve("./foo.js"),
                pathToFileURL(process.cwd()).href + "/foo.js"
            );
        });

        it("works if a full url is provided", () => {
            assert.equal(
                System.resolve("https://unpkg.com/systemjs/dist/system.js"),
                "https://unpkg.com/systemjs/dist/system.js"
            );
        });

        it("works if a full file path is provided", () => {
            assert.equal(
                System.resolve("file://Users/name/foo.js"),
                "file://Users/name/foo.js"
            );
        });

        it("works with relative file path and specified parentUrl", () => {
            assert.equal(
                System.resolve("./foo.js", "http://localhost:8321/path/"),
                "http://localhost:8321/path/foo.js"
            );
        });

        it("allows the base URL to be set to a valid full URL", () => {
            System.setBaseUrl("http://localhost:9650/some-prefix/");
            assert.equal(
                System.resolve("./foo.js"),
                "http://localhost:9650/some-prefix/foo.js"
            );
        });
    });

    describe("import maps", () => {
        it("can load a module from the network", async () => {
            System.applyImportMap({
                imports: {
                    rxjs: "https://unpkg.com/@esm-bundle/rxjs@6.5.4-fix.0/system/rxjs.min.js",
                },
            });
            const rxjs = await System.import("rxjs");
            assert.ok(rxjs.Observable);
        });

        it("can load a module from disk without setting base url, before prepareImport is called", async () => {
            System.applyImportMap({
                imports: {
                    foo:
                        "file://" +
                        path.join(
                            process.cwd(),
                            "test/fixtures/register-modules/export.js"
                        ),
                },
            });
            const foo = await System.import("foo");
            assert.equal(foo.p, 5);
        });
    });
});
